-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[CodeGen][AArch64][FMV] PAC the stub_helper's frame on arm64e #84704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-clang-codegen Author: Jon Roelofs (jroelofs) Changes... and apply default function attributes so that the resolver will also be PAC'd (once more Full diff: https://github.com/llvm/llvm-project/pull/84704.diff 6 Files Affected:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 967319bdfc4571..dadc76d04c5f6b 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4365,13 +4365,16 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
// For cpu_specific, don't create an ifunc yet because we don't know if the
// cpu_dispatch will be emitted in this translation unit.
if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
- llvm::Type *ResolverType = llvm::FunctionType::get(
+ llvm::FunctionType *ResolverType = llvm::FunctionType::get(
llvm::PointerType::get(DeclTy,
getTypes().getTargetAddressSpace(FD->getType())),
false);
- llvm::Constant *Resolver = GetOrCreateLLVMFunction(
- MangledName + ".resolver", ResolverType, GlobalDecl{},
- /*ForVTable=*/false);
+ llvm::Function *Resolver = cast<llvm::Function>(
+ CreateRuntimeFunction(ResolverType, MangledName + ".resolver")
+ .getCallee());
+ llvm::AttrBuilder Attrs(getLLVMContext());
+ addDefaultFunctionDefinitionAttributes(Attrs);
+ Resolver->addFnAttrs(Attrs);
llvm::GlobalIFunc *GIF =
llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
"", Resolver, &getModule());
@@ -4381,8 +4384,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
return GIF;
}
- llvm::Constant *Resolver = GetOrCreateLLVMFunction(
- ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
+ llvm::Function *Resolver = cast<llvm::Function>(
+ CreateRuntimeFunction(DeclTy, ResolverName).getCallee());
+ llvm::AttrBuilder Attrs(getLLVMContext());
+ addDefaultFunctionDefinitionAttributes(Attrs);
+ Resolver->addFnAttrs(Attrs);
assert(isa<llvm::GlobalValue>(Resolver) &&
"Resolver should be created for the first time");
SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
diff --git a/clang/test/CodeGen/attr-target-version-arm64e.c b/clang/test/CodeGen/attr-target-version-arm64e.c
new file mode 100644
index 00000000000000..2deff9a688daaa
--- /dev/null
+++ b/clang/test/CodeGen/attr-target-version-arm64e.c
@@ -0,0 +1,58 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs
+// RUN: %clang_cc1 -triple arm64e-apple-ios -target-feature +ls64 -target-feature +fullfp16 -S -emit-llvm -o - %s | FileCheck %s
+
+int __attribute__((target_version("sha1"))) fmv(void) { return 1; }
+int __attribute__((target_version("default"))) fmv(void) { return 0; }
+int foo() {
+ return fmv();
+}
+
+//.
+// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
+// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv
+// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
+//.
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv._Msha1
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 1
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@foo
+// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: call void @__init_cpu_features_resolver()
+// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 2048
+// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2048
+// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK: resolver_return:
+// CHECK-NEXT: ret ptr @fmv._Msha1
+// CHECK: resolver_else:
+// CHECK-NEXT: ret ptr @fmv.default
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv.default
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 0
+//
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+// CHECK: attributes #[[ATTR2]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a7fbf4aeb74494..3b7e9c282120f9 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -603,16 +603,21 @@ class AsmPrinter : public MachineFunctionPass {
return nullptr;
}
+ virtual const MCExpr *
+ emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+ return Init;
+ }
+
virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) {
- llvm_unreachable(
- "Mach-O IFunc lowering is not yet supported on this target");
+ assert(false &&
+ "Mach-O IFunc lowering is not yet supported on this target");
}
virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) {
- llvm_unreachable(
- "Mach-O IFunc lowering is not yet supported on this target");
+ assert(false &&
+ "Mach-O IFunc lowering is not yet supported on this target");
}
/// Emit N NOP instructions.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0efe7a0e733672..b70221cdec296b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2259,7 +2259,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
emitAlignment(Align(DL.getPointerSize()));
OutStreamer->emitLabel(LazyPointer);
emitVisibility(LazyPointer, GI.getVisibility());
- OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);
+ const MCSymbolRefExpr *Init = MCSymbolRefExpr::create(StubHelper, OutContext);
+ OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(Init), 8);
OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4fa719ad67cf33..f191fe3259d270 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,8 @@ class AArch64AsmPrinter : public AsmPrinter {
assert(STI);
return STI;
}
+ const MCExpr *
+ emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) override;
void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) override;
void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
@@ -1897,6 +1899,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
}
+const MCExpr *
+AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+ if (TM.getTargetTriple().isArm64e())
+ return AArch64AuthMCExpr::create(Init, /*Disc=*/0, AArch64PACKey::IA,
+ /*HasAddressDiversity=*/false, OutContext);
+
+ return Init;
+}
+
void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) {
// _ifunc:
@@ -1980,6 +1991,9 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
// ldp fp, lr, [sp], #16
// br x16
+ if (TM.getTargetTriple().isArm64e())
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::PACIBSP), *STI);
+
OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
.addReg(AArch64::SP)
.addReg(AArch64::FP)
@@ -2085,6 +2099,37 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
.addImm(2),
*STI);
+ if (TM.getTargetTriple().isArm64e()) {
+ // autibsp
+ // eor x17, lr, lr, lsl #1
+ // tbz x17, #62, Lgoodsig
+ // brk #0xc741
+ // Lgoodsig:
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::AUTIBSP), *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::EORXrs)
+ .addReg(AArch64::X17)
+ .addReg(AArch64::LR)
+ .addReg(AArch64::LR)
+ .addImm(1),
+ *STI);
+
+ MCContext &Ctx = OutStreamer->getContext();
+ MCSymbol *GoodSigSym = Ctx.createTempSymbol();
+ const MCExpr *GoodSig = MCSymbolRefExpr::create(GoodSigSym, Ctx);
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::TBZX)
+ .addReg(AArch64::X17)
+ .addImm(62)
+ .addExpr(GoodSig),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::BRK).addImm(0xc471),
+ *STI);
+
+ OutStreamer->emitLabel(GoodSigSym);
+ }
+
OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
? AArch64::BRAAZ
: AArch64::BR)
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
index 57fc2f0c9d7f5c..6f0d6f633fd513 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -1,6 +1,8 @@
; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
-; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefix=MACHO
-; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefix=MACHO
+; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
+; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
define internal ptr @the_resolver() {
entry:
@@ -21,7 +23,8 @@ entry:
; MACHO: .section __DATA,__data
; MACHO-NEXT: .p2align 3, 0x0
; MACHO-NEXT: _global_ifunc.lazy_pointer:
-; MACHO-NEXT: .quad _global_ifunc.stub_helper
+; ARM64-NEXT: .quad _global_ifunc.stub_helper{{$}}
+; PAUTH-NEXT: .quad _global_ifunc.stub_helper@AUTH(ia,0)
; MACHO: .section __TEXT,__text,regular,pure_instructions
; MACHO-NEXT: .globl _global_ifunc
@@ -30,9 +33,11 @@ entry:
; MACHO-NEXT: adrp x16, _global_ifunc.lazy_pointer@GOTPAGE
; MACHO-NEXT: ldr x16, [x16, _global_ifunc.lazy_pointer@GOTPAGEOFF]
; MACHO-NEXT: ldr x16, [x16]
-; MACHO-NEXT: br x16
+; ARM64-NEXT: br x16
+; PAUTH-NEXT: braaz x16
; MACHO-NEXT: .p2align 2
; MACHO-NEXT: _global_ifunc.stub_helper:
+; PAUTH-NEXT: pacibsp
; MACHO-NEXT: stp x29, x30, [sp, #-16]!
; MACHO-NEXT: mov x29, sp
; MACHO-NEXT: stp x1, x0, [sp, #-16]!
@@ -57,7 +62,13 @@ entry:
; MACHO-NEXT: ldp x3, x2, [sp], #16
; MACHO-NEXT: ldp x1, x0, [sp], #16
; MACHO-NEXT: ldp x29, x30, [sp], #16
-; MACHO-NEXT: br x16
+; PAUTH-NEXT: autibsp
+; PAUTH-NEXT: eor x17, x30, x30, lsl #1
+; PAUTH-NEXT: tbz x17, #62, [[GOOD_SIG:Ltmp[0-9]+]]
+; PAUTH-NEXT: brk #0xc471
+; PAUTH-NEXT: [[GOOD_SIG]]:
+; ARM64-NEXT: br x16
+; PAUTH-NEXT: braaz x16
@weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver
|
@llvm/pr-subscribers-clang Author: Jon Roelofs (jroelofs) Changes... and apply default function attributes so that the resolver will also be PAC'd (once more Full diff: https://github.com/llvm/llvm-project/pull/84704.diff 6 Files Affected:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 967319bdfc4571..dadc76d04c5f6b 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4365,13 +4365,16 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
// For cpu_specific, don't create an ifunc yet because we don't know if the
// cpu_dispatch will be emitted in this translation unit.
if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
- llvm::Type *ResolverType = llvm::FunctionType::get(
+ llvm::FunctionType *ResolverType = llvm::FunctionType::get(
llvm::PointerType::get(DeclTy,
getTypes().getTargetAddressSpace(FD->getType())),
false);
- llvm::Constant *Resolver = GetOrCreateLLVMFunction(
- MangledName + ".resolver", ResolverType, GlobalDecl{},
- /*ForVTable=*/false);
+ llvm::Function *Resolver = cast<llvm::Function>(
+ CreateRuntimeFunction(ResolverType, MangledName + ".resolver")
+ .getCallee());
+ llvm::AttrBuilder Attrs(getLLVMContext());
+ addDefaultFunctionDefinitionAttributes(Attrs);
+ Resolver->addFnAttrs(Attrs);
llvm::GlobalIFunc *GIF =
llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
"", Resolver, &getModule());
@@ -4381,8 +4384,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
return GIF;
}
- llvm::Constant *Resolver = GetOrCreateLLVMFunction(
- ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
+ llvm::Function *Resolver = cast<llvm::Function>(
+ CreateRuntimeFunction(DeclTy, ResolverName).getCallee());
+ llvm::AttrBuilder Attrs(getLLVMContext());
+ addDefaultFunctionDefinitionAttributes(Attrs);
+ Resolver->addFnAttrs(Attrs);
assert(isa<llvm::GlobalValue>(Resolver) &&
"Resolver should be created for the first time");
SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
diff --git a/clang/test/CodeGen/attr-target-version-arm64e.c b/clang/test/CodeGen/attr-target-version-arm64e.c
new file mode 100644
index 00000000000000..2deff9a688daaa
--- /dev/null
+++ b/clang/test/CodeGen/attr-target-version-arm64e.c
@@ -0,0 +1,58 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs
+// RUN: %clang_cc1 -triple arm64e-apple-ios -target-feature +ls64 -target-feature +fullfp16 -S -emit-llvm -o - %s | FileCheck %s
+
+int __attribute__((target_version("sha1"))) fmv(void) { return 1; }
+int __attribute__((target_version("default"))) fmv(void) { return 0; }
+int foo() {
+ return fmv();
+}
+
+//.
+// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
+// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv
+// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
+//.
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv._Msha1
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 1
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@foo
+// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: call void @__init_cpu_features_resolver()
+// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 2048
+// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2048
+// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK: resolver_return:
+// CHECK-NEXT: ret ptr @fmv._Msha1
+// CHECK: resolver_else:
+// CHECK-NEXT: ret ptr @fmv.default
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv.default
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 0
+//
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+// CHECK: attributes #[[ATTR2]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a7fbf4aeb74494..3b7e9c282120f9 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -603,16 +603,21 @@ class AsmPrinter : public MachineFunctionPass {
return nullptr;
}
+ virtual const MCExpr *
+ emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+ return Init;
+ }
+
virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) {
- llvm_unreachable(
- "Mach-O IFunc lowering is not yet supported on this target");
+ assert(false &&
+ "Mach-O IFunc lowering is not yet supported on this target");
}
virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) {
- llvm_unreachable(
- "Mach-O IFunc lowering is not yet supported on this target");
+ assert(false &&
+ "Mach-O IFunc lowering is not yet supported on this target");
}
/// Emit N NOP instructions.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0efe7a0e733672..b70221cdec296b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2259,7 +2259,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
emitAlignment(Align(DL.getPointerSize()));
OutStreamer->emitLabel(LazyPointer);
emitVisibility(LazyPointer, GI.getVisibility());
- OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);
+ const MCSymbolRefExpr *Init = MCSymbolRefExpr::create(StubHelper, OutContext);
+ OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(Init), 8);
OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4fa719ad67cf33..f191fe3259d270 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,8 @@ class AArch64AsmPrinter : public AsmPrinter {
assert(STI);
return STI;
}
+ const MCExpr *
+ emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) override;
void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) override;
void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
@@ -1897,6 +1899,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
}
+const MCExpr *
+AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+ if (TM.getTargetTriple().isArm64e())
+ return AArch64AuthMCExpr::create(Init, /*Disc=*/0, AArch64PACKey::IA,
+ /*HasAddressDiversity=*/false, OutContext);
+
+ return Init;
+}
+
void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
MCSymbol *LazyPointer) {
// _ifunc:
@@ -1980,6 +1991,9 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
// ldp fp, lr, [sp], #16
// br x16
+ if (TM.getTargetTriple().isArm64e())
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::PACIBSP), *STI);
+
OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
.addReg(AArch64::SP)
.addReg(AArch64::FP)
@@ -2085,6 +2099,37 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
.addImm(2),
*STI);
+ if (TM.getTargetTriple().isArm64e()) {
+ // autibsp
+ // eor x17, lr, lr, lsl #1
+ // tbz x17, #62, Lgoodsig
+ // brk #0xc741
+ // Lgoodsig:
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::AUTIBSP), *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::EORXrs)
+ .addReg(AArch64::X17)
+ .addReg(AArch64::LR)
+ .addReg(AArch64::LR)
+ .addImm(1),
+ *STI);
+
+ MCContext &Ctx = OutStreamer->getContext();
+ MCSymbol *GoodSigSym = Ctx.createTempSymbol();
+ const MCExpr *GoodSig = MCSymbolRefExpr::create(GoodSigSym, Ctx);
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::TBZX)
+ .addReg(AArch64::X17)
+ .addImm(62)
+ .addExpr(GoodSig),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::BRK).addImm(0xc471),
+ *STI);
+
+ OutStreamer->emitLabel(GoodSigSym);
+ }
+
OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
? AArch64::BRAAZ
: AArch64::BR)
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
index 57fc2f0c9d7f5c..6f0d6f633fd513 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -1,6 +1,8 @@
; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
-; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefix=MACHO
-; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefix=MACHO
+; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
+; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
define internal ptr @the_resolver() {
entry:
@@ -21,7 +23,8 @@ entry:
; MACHO: .section __DATA,__data
; MACHO-NEXT: .p2align 3, 0x0
; MACHO-NEXT: _global_ifunc.lazy_pointer:
-; MACHO-NEXT: .quad _global_ifunc.stub_helper
+; ARM64-NEXT: .quad _global_ifunc.stub_helper{{$}}
+; PAUTH-NEXT: .quad _global_ifunc.stub_helper@AUTH(ia,0)
; MACHO: .section __TEXT,__text,regular,pure_instructions
; MACHO-NEXT: .globl _global_ifunc
@@ -30,9 +33,11 @@ entry:
; MACHO-NEXT: adrp x16, _global_ifunc.lazy_pointer@GOTPAGE
; MACHO-NEXT: ldr x16, [x16, _global_ifunc.lazy_pointer@GOTPAGEOFF]
; MACHO-NEXT: ldr x16, [x16]
-; MACHO-NEXT: br x16
+; ARM64-NEXT: br x16
+; PAUTH-NEXT: braaz x16
; MACHO-NEXT: .p2align 2
; MACHO-NEXT: _global_ifunc.stub_helper:
+; PAUTH-NEXT: pacibsp
; MACHO-NEXT: stp x29, x30, [sp, #-16]!
; MACHO-NEXT: mov x29, sp
; MACHO-NEXT: stp x1, x0, [sp, #-16]!
@@ -57,7 +62,13 @@ entry:
; MACHO-NEXT: ldp x3, x2, [sp], #16
; MACHO-NEXT: ldp x1, x0, [sp], #16
; MACHO-NEXT: ldp x29, x30, [sp], #16
-; MACHO-NEXT: br x16
+; PAUTH-NEXT: autibsp
+; PAUTH-NEXT: eor x17, x30, x30, lsl #1
+; PAUTH-NEXT: tbz x17, #62, [[GOOD_SIG:Ltmp[0-9]+]]
+; PAUTH-NEXT: brk #0xc471
+; PAUTH-NEXT: [[GOOD_SIG]]:
+; ARM64-NEXT: br x16
+; PAUTH-NEXT: braaz x16
@weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver
|
// CHECK: resolver_return: | ||
// CHECK-NEXT: ret ptr @fmv._Msha1 | ||
// CHECK: resolver_else: | ||
// CHECK-NEXT: ret ptr @fmv.default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The machinery to sign these hasn't been upstreamed yet, but they'll be e.g. @fmv.default.pauth
when that happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks useful for arm64 as well, could you reveal more details on the machinery and approach to PAC resolver?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing that's missing is this:
along with this hunk:
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2893,7 +2893,11 @@ static void CreateMultiVersionResolverReturn(CodeGenModule &CGM,
llvm::Function *FuncToReturn,
bool SupportsIFunc) {
if (SupportsIFunc) {
- Builder.CreateRet(FuncToReturn);
+ llvm::Constant *Fn = FuncToReturn;
+ if (CGM.getContext().getTargetInfo().getTriple().isArm64e())
+ Fn = CGM.getConstantSignedPointer(
+ Fn, 0, nullptr, llvm::Constant::getNullValue(CGM.SizeTy));
+ Builder.CreateRet(Fn);
return;
}
This arranges for the resolver to return signed function pointers. There is no difference for arm64(non-e).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asl the check in the hunk above should be generalized for ELF, and only turned on with -fptrauth-calls
. I wasn't sure how to get a QualType here though, which would be needed to get the CGPointerAuthInfo
that this would make the check on. Not sure if it's reasonable to "invent" one that's close enough, e.g. for void (*fn_ptr)(void);
or something.
Tagging @kovdan01 Can the triple checks be generalized to checking about pauth-enabled subtarget feature? This way everything would work for ELF platforms eventually. |
@asl Since I'm not sure how particularly ifuncs should be handled, here are two answers for two different cases. If we need just to check that pauth target feature is enabled, we can use If the ifunc-related behavior is dependent on |
These are admittedly a bit of a hack, since we don't have a Function to look at the attributes on when we're in that part of the AsmPrinter. But that said, the ones in the AsmPrinter are all Mach-O-specific: they "manually" implement what the dynamic linker would do on an ELF platform, so generalizing them won't help ELF platforms.
The change to add the default attributes should cover whether the resolver gets For |
@@ -2085,6 +2099,37 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M, | |||
.addImm(2), | |||
*STI); | |||
|
|||
if (TM.getTargetTriple().isArm64e()) { | |||
// autibsp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave the tail-call checking for the general tail-call checking patches, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a PR up for that that I should tack this bit onto the end of?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is not, but send me your patch and I'll tack it onto the relevant commit (and split the tail-call check emission into a helper)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ With the latest revision this PR passed the C/C++ code formatter. |
... and apply default function attributes so that the resolver will also be PAC'd (once more
arm64e
patches land upstream).